package ast


/*
exp ::=  nil | false | true | Numeral | LiteralString | ‘...’ | functiondef |
	 prefixexp | tableconstructor | exp binop exp | unop exp

prefixexp ::= var | functioncall | ‘(’ exp ‘)’

var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name

functioncall ::=  prefixexp args | prefixexp ‘:’ Name args
*/


type Exp interface{}


type NilExp struct {		// nil
	Line 		int
}


type TrueExp struct {
	Line 		int 		// true
}


type FalseExp struct {		// false
	Line 		int 
}


type VarargExp struct {		// ...
	Line 		int 		
}


// Numeral
type IntegerExp struct {
	Line 		int
	Val 		int64
}

type FloatExp struct {
	Line 		int 
	Val 		float64
}


// LiteralString
type StringExp struct {
	Line 		int 
	Str 		string
}


// unop exp
type UnopExp struct {
	Line 		int 	// line of operator
	Op 			int 	// operator
	Exp 		Exp
}

// exp1 op exp2
type BinopExp struct {
	Line 		int 	// line of operator
	Op 			int 	// operator
	Exp1 		Exp
	Exp2 		Exp
}


// 由于拼接运算的特殊性，我们需要给它定义结构体
// 在语法分析阶段，我们会把连续的多个拼接操作收集在一起
// 这样就可以很方便地在代码生成阶段使用一条CONCAT指令来优化拼接操作
type ConcatExp struct {
	Line 		int 	// line of last ..
	Exps		[]Exp
}


// tableconstructor ::= ‘{’ [fieldlist] ‘}’
// fieldlist ::= field {fieldsep field} [fieldsep]
// field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
// fieldsep ::= ‘,’ | ‘;’
type TableConstructorExp struct {
	Line 		int 	// line of '{'
	LastLine	int 	// line of '}'
	KeyExps		[]Exp
	ValExps		[]Exp
}


// functiondef ::= function funcbody
// funcbody ::= ‘(’ [parlist] ‘)’ block end
// parlist ::= namelist [‘,’ ‘...’] | ‘...’
// namelist ::= Name {‘,’ Name}
type FuncDefExp struct {
	Line 		int
	LastLine 	int 	// line of 'end'
	ParList 	[]string
	IsVararg	bool
	Block 		*Block
}


/*
prefixexp ::= Name |
              ‘(’ exp ‘)’ |
              prefixexp ‘[’ exp ‘]’ |
              prefixexp ‘.’ Name |
              prefixexp ‘:’ Name args |
              prefixexp args
*/

type NameExp struct {
	Line 		int
	Name 		string
}


type ParensExp struct {
	Exp 		Exp
}


type TableAccessExp struct {
	LastLine		int 		// line of ']'
	PrefixExp		Exp
	KeyExp 			Exp
}


// functioncall ::= prefixexp [':' Name] args
// args ::= '(' [explist] ')' } tablecontructor | LiteralString
type FuncCallExp struct {
	Line 			int 		// line of '('
	LastLine 		int 		// line of ')'
	PrefixExp 		Exp
	NameExp			*StringExp
	Args 			[]Exp
}